package mapper;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.List;

/*动态非必须数据放在其他类中，必须数据放在记录中
* 其他中的数据，通过对象引用，list等方式使用
* */
public record CardNoRecord(
        //固定且必须的数据放在最外面，非必须的数据封装成是实体类放在内部，类似list
        /*
         * 卡INN
         */
        String cardInnNo,
          /*
          * 卡类型
         */
        String cardType,
        /**
        * 卡组织
        */
        String cardOrg,
       /**发卡序列号列表*/
        List<Long>numberList,
        CardSerialNumber cardSerialNumber

) {
    public static class CardSerialNumber {
        /**
         * 卡序列号
         */
        private String serialNumber;

        /**
         * 当前的卡号段序列号
         */
        private Long nowSeq;

        /**
         * 结束的卡号段序列号
         */
        private Long endSeq;

        /**
         * 卡号段剩余序号
         */
        private Long residueNum;
        /**
         * 产品单价，即卡单价
         */
        private String productPrice;

        /**
         * 之后的卡号端的序列号，用于审核之后，订单中的卡数量+当前卡号段序列号
         */
        private Long afterSerialNumber;

        /**发卡数量*/
        private  Long cardCount;

        @Override
        public String toString() {
            return "CardSerialNumber{" +
                    "serialNumber='" + serialNumber + '\'' +
                    ", nowSeq=" + nowSeq +
                    ", endSeq=" + endSeq +
                    ", residueNum=" + residueNum +
                    ", productPrice='" + productPrice + '\'' +
                    ", afterSerialNumber=" + afterSerialNumber +
                    ", cardCount=" + cardCount +
                    '}';
        }

        public String getSerialNumber() {
            return serialNumber;
        }

        public void setSerialNumber(String serialNumber) {
            this.serialNumber = serialNumber;
        }

        public Long getNowSeq() {
            return nowSeq;
        }

        public void setNowSeq(Long nowSeq) {
            this.nowSeq = nowSeq;
        }

        public Long getEndSeq() {
            return endSeq;
        }

        public void setEndSeq(Long endSeq) {
            this.endSeq = endSeq;
        }

        public Long getResidueNum() {
            return residueNum;
        }

        public void setResidueNum(Long residueNum) {
            this.residueNum = residueNum;
        }

        public String getProductPrice() {
            return productPrice;
        }

        public void setProductPrice(String productPrice) {
            this.productPrice = productPrice;
        }

        public Long getAfterSerialNumber() {
            return afterSerialNumber;
        }

        public void setAfterSerialNumber(Long afterSerialNumber) {
            this.afterSerialNumber = afterSerialNumber;
        }

        public Long getCardCount() {
            return cardCount;
        }

        public void setCardCount(Long cardCount) {
            this.cardCount = cardCount;
        }
    }
    /**
     * 行业号,默认值01
     */
    static String industry="01";

    /**记录类转卡面号*/
    public @NotNull String toCardFaceNo(){
        return buildCardFaceNo(this.cardSerialNumber.serialNumber);
    }
    private static String cardBinToCardOrg(@NotNull String cardBin) {
        return switch (cardBin) {
            case "098" -> "009";
            case "097" -> "008";
            default -> "007";

        };
    }
    @NotNull
    private String buildCardFaceNo(@NotNull String serialNumber) {
        final int length = serialNumber.length();
        String cardSerialNumber;
        String jtbCardType;
        if (length <8){
            //小于8位，补零到8位
            cardSerialNumber= StrUtil.padPre(serialNumber, 8, '0');
            jtbCardType = cardType.substring(0, 2);
        }else{
            //大于8位，只取最后8位
            cardSerialNumber=StrUtil.sub(serialNumber,
                    -8,
                    length);
            jtbCardType=serialNumber.substring(0,2);
        }
        return switch (cardOrg) {
            case "098" ->
                //取2位为卡类型填充流水号
                    cardInnNo + jtbCardType + cardSerialNumber;
            case "096" ->
                //行业号+补0到10位
                    industry + StrUtil.padPre(cardSerialNumber, 10, '0');
            default -> cardInnNo + this.cardSerialNumber.serialNumber;
        };
    }
    /**记录类生成NumberList和afterNumber
     * flag 是否进行数据校准。
     * 进行数据校准，则生成的序列号列表来源于结束卡号段
     * 不进行数据校准：则生成的序列号列表来源于当前卡号段和卡数量
     * */
    private void buildNumberListAndAfterNumber(boolean flag) {
        Long nowSeq = cardSerialNumber.nowSeq;
        final Long cardCount = cardSerialNumber.cardCount;
        final Long residueNum = cardSerialNumber.residueNum;
        final Long endSeq = cardSerialNumber.endSeq;

        Assert.notNull(nowSeq);
        Assert.notNull(cardCount);
        if (flag) {
            Assert.notNull(residueNum);
            //数据校准
            nowSeq= endSeq - residueNum + 1;
            Assert.checkBetween(nowSeq + cardCount - 1, 1,
                    endSeq, "订单数量超出号段结束长度，请进行调整");
        }
        Assert.notNull(nowSeq);
        //数据自增+数据填充
        for (int i = 0; i < cardCount; i++) {
            numberList.add(nowSeq+i);
        }

        //最后一个元素即最后的序列号
        cardSerialNumber.afterSerialNumber=numberList.get(numberList.size() - 1);
    }
    /**记录类根据NumberList转化为卡面号列表*/
    public @NotNull List<String> toCardFaceNoListByNumberList(boolean flag){
        //不存在则生成numberList
        if (CollUtil.isEmpty(numberList)){
            buildNumberListAndAfterNumber(flag);
        }
        final ArrayList<String> cardFaceNoList = new ArrayList<>(numberList.size());
        for (Long number : numberList) {
            cardFaceNoList.add(buildCardFaceNo(number.toString()));
        }
        return cardFaceNoList;
    }

    public static void main(String[] args) {
        final String cardOrg = "098";
        final CardNoRecord cardNoRecord = new CardNoRecord(cardBinToCardOrg(cardOrg), "29", cardOrg,
                new ArrayList<>(16), new CardSerialNumber());
        final List<Long> longs = cardNoRecord.numberList();
        longs.add(12L);
        longs.add(18L);
        cardNoRecord.cardSerialNumber().setSerialNumber("177");
        System.out.println(longs);
        System.out.println(cardNoRecord);
        System.out.println(cardNoRecord.toCardFaceNo());
    }


}
